
package org.japril.swing.jutil.xmloperations;

import java.io.File;
import java.io.IOException;
import java.util.Properties;

import org.japril.jutil.JavaCodeBuilder;
import org.japril.jutil.xmloperations.XmlOperation;
import org.japril.jutil.xmloperations.XmlOperations;

/**
 * <p>
 * </p>
 * @author Arne Halvorsen (AH)
 */
public final class XmlOperationsToJavaCode
{
  private final File m_dir;
  
  /**
   * <p>
   *   Constructor.
   * </p>
   * @param dir Directory to create source files in.
   */
  public XmlOperationsToJavaCode(File dir)
  {
    if (dir==null)
    {
      throw new NullPointerException("dir");
    }
    if (!dir.isDirectory())
    {
      throw new NullPointerException("not a directory: "+dir);  
    }
    
    m_dir=dir;
  }
  
  public void generateXmlOperationsFactory(XmlOperations ops) throws IOException
  {
    if (ops==null)
    {
      throw new NullPointerException("ops");
    }
    
    Properties props=System.getProperties();
    String pack=props.getProperty("gen-source-package", "org.cm.xmloperations");
    
    JavaCodeBuilder jcb=new JavaCodeBuilder();
    
    jcb.println().pack(pack).println()
       .imports(XmlOperations.class).println()
       .publicMod().finalMod(false).clazz("XmlOperationFactory")
       .begin()
         .privateMod().constructor().dohtem().beginend().println()
         
         .publicMod().staticMod(false).method("create", XmlOperations.class)
         .dohtem()
         .begin()
           .println("XmlOperations retVal=new XmlOperations();", true);
    
           int n=ops.size();
           for (int i=0; i<n; i++)
           {
             XmlOperation o=ops.getOperation(i);
             String name=o.getName();
             String cname=checkName(name);
             jcb.println("retVal.addOperation(new "+cname+"());", true);
           }
         
         jcb.print("return retVal;", true);
           
         jcb.end()
       
     .end();
    
    jcb.generateFile(m_dir);
  }
  
  public void generateXmlOperation(XmlOperation o) throws IOException
  {
    if (o==null)
    {
      throw new NullPointerException("o");
    }
    
    Properties props=System.getProperties();
    String pack=props.getProperty("gen-source-package", "org.cm.xmloperations");
    
    JavaCodeBuilder jcb=new JavaCodeBuilder();
    
    String name=o.getName();
    String cname=checkName(name);
    
    int pc=o.getPathCount();
    
    jcb.println().pack(pack).println()
       .imports(XmlOperation.class).println()
       .publicMod().clazz(cname, XmlOperation.class)
       .begin()
         .publicMod().constructor().dohtem().beginend().println()
         
         .publicMod().method("getName", String.class).dohtem()
         .begin()
           .print("return \""+name+"\";")
         .end().println()
         
         .publicMod().method("getDesc", String.class).dohtem()
         .begin()
           .print("return null;", true)
         .end().println()
         
         .publicMod().method("getPathCount", Integer.TYPE).dohtem()
         .begin()
           .print("return "+pc+";", true)
         .end().println()
         
         .publicMod().method("getPath", String.class).fpar(Integer.TYPE, "idx")
         .dohtem()
         .begin()
           .print("switch(idx)", true)
           .begin();
    
             for (int i=0; i<pc; i++)
             {
               String path=o.getPath(i);
               jcb.print("case "+i+" : return ", true);
               jcb.string(path).println(";");
             }
     jcb     .print("default : throw new IndexOutOfBoundsException();", true)      
           .end()
         .end().println()
         
         .publicMod().method("perform").fpar(String.class, "xml").dohtem()
         .begin()
           .print("System.out.println(getName()+\" performs\");", true)
         .end()
         
       .end();
    
    jcb.generateFile(m_dir);
  }
  
  private String checkName(String name)
  {
    int n=name.length();
    
    StringBuilder sb=new StringBuilder();
    
    char c0=name.charAt(0);
    if (!Character.isJavaIdentifierStart(c0))
    {
      throw new IllegalArgumentException(name+" not usable as class name");
    }
    
    sb.append(Character.toUpperCase(c0));
    
    for (int i=1; i<n; i++) 
    {
      char c=name.charAt(i);
      if (!Character.isJavaIdentifierPart(c))
      {
        throw new IllegalArgumentException(name+" not usable as class name");
      }
      
      sb.append(c);
    }
    
    sb.append("XmlOperation");
    
    return sb.toString();
  }
  
}
